import { createElement } from "../../../utils";
import { ROW_HEIGHT, tableTemplateData } from "../../../const";
import BaseNode from "../../BaseNode";

interface CellDataType extends VoucherTableCol {
  width: number;
  height: number;
  align: string;
}

export default class TableNode extends BaseNode {
  element = createElement("div");
  private _tableEl = createElement("table", { style: { "border-spacing": "0", "border-collapse": "collapse" } });

  protected _tbodyEl = createElement("tbody");
  protected _nodeType: VoucherNodeType = "table";
  protected _options: VoucherTableTemplate = tableTemplateData()

  protected contentEls: { trEl: HTMLElement; cells: (HTMLElement | null)[] }[] = []
  protected get contentData(): VoucherTableTemplate["content"] {
    return this.options.content;
  }

  protected set contentData(content: VoucherTableTemplate["content"]) {
    this.options.content = content;
  }

  public get options() {
    return { ...this._options };
  }


  constructor({ name, align, border, borderColor, borderWidth, x, y, content }: VoucherTableTemplate) {
    super();
    this.setOptions({ name, align, border, borderColor, borderWidth, x, y });
    this.contentData = content;
    this.initContent();
  }

  public setOptions({ name, align, border, borderColor, borderWidth, x, y }: Partial<VoucherTableTemplate>) {
    if (name !== undefined) this._options.name = name
    if (x !== undefined) this._options.x = x
    if (y !== undefined) this._options.y = y
    if (align !== undefined) this._options.align = align
    if (border !== undefined) this._options.border = border
    if (borderColor !== undefined) this._options.borderColor = borderColor
    if (borderWidth !== undefined) this._options.borderWidth = borderWidth
    this.render()
  }

  private render() {
    const { name, align, border, borderColor, borderWidth, x, y } = this.options
    this.element.style.left = `${x}px`;
    this.element.style.top = `${y}px`;
    this._tableEl.style.textAlign = align
    this._tableEl.style.borderColor = borderColor
    this._tableEl.style.borderWidth = `${borderWidth}px`
    if (border) {
      this._tableEl.setAttribute("border", "1")
    } else {
      this._tableEl.removeAttribute("border")
    }
  }

  private initContent() {
    const { content } = this.options
    this.contentEls = content.rows.map((row, i) => this.createRowEl(row, i))
    this._tableEl.appendChild(this._tbodyEl)
    this.element.appendChild(this._tableEl)
  }

  protected createCellEl(cellData: CellDataType, rowIndex: number, colIndex: number) {
    const { width, height, align, colspan, rowspan } = cellData

    const style: { [key: string]: string } = { borderWidth: `${this.options.borderWidth}px` }
    if (colspan < 1 || rowspan < 1) {
      style.display = "none"
    }
    const cellEl = createElement("div", { style: { width: `${width * colspan}px`, height: `${height * rowspan}px`, overflow: "auto", textAlign: align, "scrollbar-width": "none", padding: "0 5px" } })
    cellEl.setAttribute("data-row-index", rowIndex.toString())
    cellEl.setAttribute("data-col-index", colIndex.toString())
    const tdEl = createElement("td", { style, content: cellEl, })
    tdEl.setAttribute("colspan", colspan.toString())
    tdEl.setAttribute("rowspan", rowspan.toString())
    tdEl.setAttribute("data-col-index", colIndex.toString())
    return tdEl
  }

  protected createRowEl(row: VoucherTableRow, rowIndex: number) {
    const trEl = createElement("tr")
    trEl.setAttribute("data-row-index", rowIndex.toString())
    const colsconfig = this.contentData.cols
    const rowData = {
      trEl,
      cells: row.cells.map((cell, colIndex) => {
        if (!cell) return null
        const col = colsconfig[colIndex]
        const tdEl = this.createCellEl(Object.assign({ width: col.width, height: ROW_HEIGHT, align: col.align }, cell), rowIndex, colIndex)
        trEl.appendChild(tdEl)
        return tdEl
      })
    }
    this._tbodyEl.appendChild(trEl)
    return rowData
  }



  public getOptions(): VoucherTableTemplate {
    return this.options
  }
}